from Mesh.Mesh1D import Mesh1D
from FVMEqn.FVMEqn import FVMEqns
import Device.PhysUnit as Unit
from Device.DDEqns import SemiconductorRegionEqn,OhmicBoundaryEqn
from Materials.HgCdTeProperties import HgCdTe
import numpy as np
import math

LightIsOn = False
LightfromPside = True
I0 = 1e-3*Unit.W/pow(Unit.cm,2)
wavelength=3.8*Unit.um
hv = (6.6260693e-34*Unit.J*Unit.s)*(3e8*Unit.m/Unit.s)/wavelength

MCTcomposition=0.29

class Diode(Mesh1D):
    def __init__(self):
        NN = 400
        #在这里规定了格点的分布和数量（尺寸）：
        xx = np.linspace(-0.65e-4*Unit.cm, 7e-4*Unit.cm, NN+1)
        self.h = xx[1]-xx[0]
        Mesh1D.__init__(self, xx, 
                        rgns=[(0, NN, 'mct')],
                        bnds=[(0,'anode'),(NN,'cathode')])
        if LightfromPside :
            self.illumination_edge = self.getRegion('mct').cells[0].node.pos
        else:
            self.illumination_edge = self.getRegion('mct').cells[NN].node.pos
        #设定材料属性：
        self.setRegionMaterial('mct', HgCdTe(composition=MCTcomposition, Temperature=300*Unit.K))
        self.alpha = 5e3 * pow(Unit.cm,-1)
        
        #这里设定掺杂分布情况：
        def doping(x):
            if x<0:
                return -3e18*pow(Unit.cm,-3)  #负号是p型区掺杂剂的固定电荷？
            elif x>0:
                return +1e16*pow(Unit.cm,-3)   #正号是n型区掺杂的固定电荷？
            else:
                return 0.0
        
        #这里设定光照强度产生的产生率：
        def light_Gen(x):
            if LightIsOn :
                if LightfromPside :
                    Ix = I0 * (math.exp(-1.0*( x - self.illumination_edge) * self.alpha))
                else :
                    Ix = I0 * (math.exp(-1.0*( self.illumination_edge - x) * self.alpha))
                dI = Ix * self.alpha 
                if (Ix==I0) : 
                    print ('illuminate@ %d : photo generate %e cm-3*s-1'%(x, dI/hv*Unit.s*pow(Unit.cm,3)))                 
                return dI/hv  #Unit: 1/(s*m^3)
            else:
                return 0.0   
            
        self.setFieldByFunc(0, 'C', doping) #调用doping函数给'C'字典变量赋值？ C是一个字典项的名字？是Charge吗？
        self.setFieldByFunc(0, 'Light', light_Gen)

class DiodeEqns(FVMEqns):  #注释： FVMEqns 是 DiodeEquns 的 基类 
    def __init__(self, device):
        super(DiodeEqns, self).__init__(device) #利用传递来的参数初始化这个基类？FVMEqns按照device来初始化。

        self.eqnSi = SemiconductorRegionEqn()
        self.setRegionEqn('mct', self.eqnSi)

        self.bcAnode = OhmicBoundaryEqn()
        self.bcCathode = OhmicBoundaryEqn()
        self.setBoundaryEqn('anode', self.bcAnode)
        self.setBoundaryEqn('cathode', self.bcCathode)
        self.setupEqns()
def findR0A(Voltages,Currents):
    '''
    #利用零点附近的电流电压关系,计算R0A和短路电流
    '''
    Resistance = 0.0
    short_current = 0.0
    for index in range(0,len(Voltages)-1) :
        if (Voltages[index] == 0.00) :
            Resistance = (Voltages[index+1] - Voltages[index-1]) / (Currents[index+1] - Currents[index-1])
            short_current = Currents[index]
            break
        elif ((Voltages[index]) * (Voltages[index+1]) < 0.0):
            Resistance = (Voltages[index+1] - Voltages[index]) / (Currents[index+1] - Currents[index])
            short_current = Currents[index]
            break
        else:
            if index==len(Voltages)-1 : print ('Error in Finding R0A resistance. ')
    return Resistance,short_current

if __name__ == '__main__':
    LightIsOn = True
    #LightIsOn = False	
    if LightIsOn : 
        print ('---- light is ON ----')
        print ('I0 =',I0/(Unit.W/pow(Unit.cm,2)),'W/cm^2')
        print ('Wavelength =',wavelength/(Unit.um),'um')
    else : 
        print ('---- light is OFF ----')
    MCTcomposition = 0.29
    print ('MCT x=', MCTcomposition)
    print('=========================================')
    diode = Diode()
    diodeEqn = DiodeEqns(diode)
    diodeEqn.initGuess()
    #diodeEqn.bcAnode.setVoltage(0.0)
    #diodeEqn.solve()

    #下面扫描零偏压附近的偏置求解，并利用器件内部前两个节点的数据计算器件内部的电流
    Voltages = []
    Currents = []
    h = diode.h
    VT = 0.0258*Unit.V
    for biasindex in range(-3,3,1): #注意需要必须有一个是零点，这样才好计算零偏阻抗
        volt = biasindex*0.01*Unit.V
        Voltages.append(volt)
        diodeEqn.bcAnode.setVoltage(volt)
        diodeEqn.solve()
        vi = diode.getVarIdx('mct', 0) # potential in Substrate
        Potential =(diodeEqn.state.x[vi])
        ElecField = -(Potential[2]-Potential[1])/h
        ni = diode.getVarIdx('mct', 1) # electron conc in Substrate
        ElecConc = (diodeEqn.state.x[ni])
        dndx = (ElecConc[2]-ElecConc[1])/h
        mobilityn = diode.getRegion('mct').material.mun
        #print ('mobility=',mobility) 
        pi = diode.getVarIdx('mct', 2) # hole conc in Substrate
        HoleConc = (diodeEqn.state.x[pi])
        mobilityp = diode.getRegion('mct').material.mup
        dpdx = (HoleConc[2]-HoleConc[1])/h
        ElecCurrent1 = Unit.e * mobilityn *(ElecConc[1]*ElecField +VT*dndx ) 
        HoleCurrent2 = Unit.e * mobilityp *(HoleConc[1]*ElecField -VT*dpdx ) 
        Current = ElecCurrent1 + HoleCurrent2
        Currents.append(Current)

    #
    #找出R0A:
    Resistance,short_current = findR0A(Voltages,Currents)
    #输出结果
    print(' ')
    print('=========================================')
    print('          R0A = % e Ohm*cm^2'%(Resistance/(Unit.V/Unit.A)/pow(Unit.cm,2)))
    print('Short_current = % e A/cm^2'%(short_current/Unit.A*pow(Unit.cm,2)))
    if LightIsOn : 
        Ri = -(short_current/I0)/(Unit.A/Unit.W)
        QE = Ri/(Unit.A/Unit.W)/(wavelength/Unit.um)*124
        print(' Responsivity = % f A/W' % (Ri))
        print('    Quan_effi = % d%%' % (QE))
